perm filename EFSPKT.C[11,HE] blob
sn#688192 filedate 1982-12-06 generic text, type T, neo UTF8
/* LINTLIBRARY */
/*
* efsendpckt..c
*
* EFTP Package
*
* THIS ASSUMES NOTHING ABOUT BYTE ORDER.
* EfSendPckt -- send the next packet of an Eftp transfer
*
* Jeffrey Mogul @ Stanford 28-January-1981
*/
#define min(a,b) ( (a<b)? a : b )
#include <pupconstants.h>
#include <pupstatus.h>
#include <eftp.h>
EfSendPckt(Efchan, buf, blen)
struct EftpChan *Efchan; /* open eftp channel */
char *buf; /* data buffer */
int blen; /* number of bytes to send */
{ /* */
int retry;
int inhibit; /* INVARIANT -- MUST BE 0 or 1 */
int rstat;
uchar rpuptype;
ulong rpupid;
char msgbuf[100];
int msgbuflen;
blen = min(blen,EFTP_MAX_PACKET); /* don't send too much! */
inhibit = 0; /* don't inhibit packet sending */
for (retry=0; retry < Efchan->WaitTime ; retry++) {
/* attempt to get a packet accross */
/* the "inhibit" flag is used to avoid re-sending too
* quickly if we get a duplicate ACK; the problem is
* that an ACK for the packet we just sent may already
* be on its way, and we will get into a situation where
* every packet is sent twice if we don't watch it.
*/
if (!inhibit) /* test (and clear later) inhibit */
pupwrite(&Efchan->pchan,EFTPDATA,Efchan->sequence,
buf, blen);
/* pup id is sequence number */
inhibit = 0;
/* wait for an ACK */
rstat = pupread(&Efchan->pchan,msgbuf,&msgbuflen,
&rpuptype, &rpupid, NULL, NULL);
if (rstat == BADCKSUM || rstat == TIMEOUT) continue;
/* got a packet */
switch ((int)rpuptype) {
case EFTPACK:
if (rpupid == Efchan->sequence) { /* right ack */
Efchan->sequence++; /* incr. sequence */
return(OK);
}
else { /* got the wrong ack */
if (rpupid > Efchan->sequence) {
/* future packet acked ?! */
return(EFTP_BADACK);
}
}
/* other possibility is repeated ack; ignore it,
* but inhibit resending the packet for next
* timeout period - another ack may be coming.
*/
inhibit++;
break; /* effect is to repeat loop & retry */
case EFTPABORT:
EftpAbortCode = *(ushort *)msgbuf;
movestring(&msgbuf[2],EftpErrMsg,msgbuflen-2);
EftpErrMsg[msgbuflen-2] = 0; /* nullterm string */
return(EFTP_ABORT);
default: /* we got the wrong packet type! */
return(EFTP_ERROR);
}
}
/* too many retries */
return(TIMEOUT);
}